---
title: "Parent Flow"
type: concept
created: 2026-04-18
updated: 2026-04-18
sources: ["raw/articles/11-user-signup-flows.md", "raw/articles/05-roster.md"]
tags: [user-flows, parent, observer, invite, v1-scope]
---

# Parent Flow

In v1, parents are **linked observers only**. They cannot create child accounts, purchase access, or own the primary learner record. The child account exists within the school structure; the parent is attached afterward.

> **v1 Scope:** B2C parent-created children and consumer subscriptions are **out of scope**. All child accounts originate from the school/teacher flow.

## What Parents Can and Cannot Do (v1)

| Action | v1 |
|---|---|
| Create a child account independently | ❌ |
| Buy consumer access | ❌ |
| Own the primary learner record | ❌ |
| Move child outside school structure | ❌ |
| Receive parent invite from teacher | ✅ |
| Create own adult account (via invite) | ✅ |
| View child's tracker and reading progress | ✅ (read-only) |
| Receive weekly digest notifications | ✅ |
| Reset child PIN | ⏳ DECISION-10 |

## How a Parent Gets Linked (v1 — Teacher Invite Flow)

The canonical v1 parent link flow is **teacher-initiated**:

```mermaid
flowchart TD
    T["Teacher\nPortal → Student → Invite Parent\nPOST /api/v1/students/:id/parent-invite\n{parent_email}"]
    INV["parent_invites row inserted\ntoken_hash, expires_at = now()+7d"]
    EMAIL["PARENT_INVITE email sent\nto parent_email\nContains invite URL with token"]
    PA["Parent lands on\naccount.readingtester.com\n/parent-invite?token=UUID"]
    REG{"Has account?"}
    NEW["Register: name + password\n(email pre-filled from invite)"]
    EXIST["Sign in"]
    ACCEPT["POST /api/auth/parent-invite-accept\n{token, name, password}"]
    LINK["students.parent_id = users.id\nAudit logged\nuc_session cookie set"]
    DASH["Redirect to\nparents.readingtester.com\n/child/:learner_id"]
    T --> INV --> EMAIL --> PA --> REG
    REG -->|new user| NEW --> ACCEPT
    REG -->|existing| EXIST --> ACCEPT
    ACCEPT --> LINK --> DASH
```

**Critical rule:** This flow attaches a parent to an existing child record. It **never creates a new student row**.

**Failure paths:**

| Condition | Error |
|---|---|
| Token expired (>7 days) | "Link expired. Ask the teacher to resend." |
| Token already used | "Already linked. Sign in to view." |
| Email mismatch | "This link was sent to a different email address." |
| Child already has a different parent | "Contact school admin." |

## Parent Claim Flow (Alternative)

Parents can also link by self-initiating via the Parent Portal onboarding wizard:

1. Parent registers at `account.readingtester.com` (email + password)
2. Parent Portal wizard → "Link a child" → enter child's username
3. System looks up child (returns child name + class name + school name — no PII)
4. Parent submits claim → `parent_claims` row inserted
5. Teacher receives notification: "Parent X wants to link to Student Y"
6. Teacher approves or rejects
7. On approval: `students_parents` row inserted, parent notified

**Auto-approve:** If `schools.auto_approve_parent_claims = true`, Step 5–6 are skipped.

## What Parents Can See (v1 Default)

> ⏳ **DECISION-13:** Exact scope of parent-visible data needs approval from Sig. The below is the conservative v1 default.

| Data | Parent can see |
|---|---|
| Reading history (books, dates, duration) | ✅ |
| Miles + tokens | ✅ |
| Reading level ("Reading at Grade N level") | ✅ (no FK number shown) |
| Weekly/nightly digest (warm, plain language) | ✅ |
| Raw quiz scores | ❌ |
| Intervention alerts | ❌ |
| Assignments | ❌ |
| Class roster or other children | ❌ |
| Teacher data | ❌ |

The parent digest is generated by the [[Learner Bot]] nightly run and delivered in warm, jargon-free language: "Sofia had a great reading day! She read 3 books and learned 5 new words."

## Open Decisions (v1)

These decisions are **explicitly unresolved**. Build to the current default listed. Do not implement alternatives without Sig's approval.

| ID | Decision | Current default |
|---|---|---|
| ⏳ DECISION-08 | Can one child have multiple parents linked | No (single `students.parent_id` FK). Max 2 via `students_parents` table if approved. |
| ⏳ DECISION-10 | Can parent reset child PIN | No by default; school policy can enable |
| ⏳ DECISION-12 | Can school disable parent visibility | Yes — `schools.parent_visibility_enabled` flag (flag not yet in DDL) |
| ⏳ DECISION-13 | What data can parent see | Tracker data only (see table above) — exact scope needs approval |

## Parent Portal

The parent-facing application lives at `parents.readingtester.com` (port 3118).

**Confirmed endpoints (2026-04-18):**
- `GET /api/v1/digest/preview/:child_id` — preview the nightly digest
- `GET /api/v1/gdpr/export/:id` — GDPR data export

**Status:** Infrastructure built. No real digests yet — awaiting nightly bot + parent email pipeline.

## Consent Model — v1 Locked (Sig, 2026-04-18)

- Student accounts are activated under the **school DPA** — no per-student parental consent gate in the platform
- Parents are **linked observers** in v1 — they can view progress and receive notifications, but their presence is not required for student activation
- Schools manage parental consent outside the platform through their own processes (letters home, school policy)
- If parent email was provided in student import CSV, a parent invite is queued automatically — this is optional engagement, not an activation requirement
- DECISION-14 is now resolved: individual per-student platform consent is out of scope for v1

**Future model (out of scope v1):** Parent-controlled consent with in-platform capture is required for any B2C path. See [[concepts/compliance/GDPR Module#Future Model: Direct-to-Consumer]].

## Related Pages

- [[concepts/user-flows/index|User Flows]] — all roles overview
- [[concepts/user-flows/Teacher Flow]] — teacher initiates parent invite
- [[concepts/user-flows/Student Flow]] — child account the parent links to
- [[entities/Account Center]] — where parent registration/login lives
